package cas.ihep.spark.io;

import java.io.DataInput;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;

@SuppressWarnings("WeakerAccess")
public class ByteBufferInputStream extends InputStream implements DataInput {
    private ByteBuffer mBuffer;
    private boolean releaseOnClose;
    public static ByteBufferInputStream newStream(ByteBuffer buf){
        ByteBufferInputStream ret=new ByteBufferInputStream();
        ret.mBuffer=buf.slice();
        ret.releaseOnClose=false;
        return ret;
    }

    public static ByteBufferInputStream newTempBufferStream(ByteBuffer buf){
        ByteBufferInputStream ret=new ByteBufferInputStream();
        ret.mBuffer=buf;
        ret.releaseOnClose=true;
        return ret;
    }

    public void close(){
        if(releaseOnClose) {
            ByteBufferUtil.releaseBuffer(mBuffer);
        }
    }

    @Override
    public void readFully(byte[] bytes) throws IOException {
        readFully(bytes,0,bytes.length);
    }

    @Override
    public void readFully(byte[] bytes, int off, int len) throws IOException {
        if(off<0 || off>=len){
            throw new IndexOutOfBoundsException();
        }
        int inlen=mBuffer.remaining();
        if(inlen>=len){
            mBuffer.get(bytes,off,len);
            return;
        }
        throw new EOFException();
    }

    @Override
    public int skipBytes(int i) {
        int pos=mBuffer.position();
        int inlen=mBuffer.limit()-pos;
        inlen=Math.min(i,inlen);
        mBuffer.position(pos+inlen);
        return inlen;
    }

    @Override
    public boolean readBoolean() throws IOException {
        if(mBuffer.remaining()>0) {
            return mBuffer.get() != 0;
        }
        throw new EOFException();
    }

    @Override
    public byte readByte() throws IOException {
        if(mBuffer.remaining()>0) {
            return mBuffer.get();
        }
        throw new EOFException();
    }

    @Override
    public int readUnsignedByte() throws IOException {
        return Byte.toUnsignedInt(readByte());
    }

    @Override
    public short readShort() throws IOException {
        if(mBuffer.remaining()>1){
            return mBuffer.getShort();
        }
        throw new EOFException();
    }

    @Override
    public int readUnsignedShort() throws IOException {
        return Short.toUnsignedInt(readShort());
    }

    @Override
    public char readChar() throws IOException {
        if(mBuffer.remaining()>1){
            return mBuffer.getChar();
        }
        throw new EOFException();
    }

    @Override
    public int readInt() throws IOException {
        if(mBuffer.remaining()>3){
            return mBuffer.getInt();
        }
        throw new EOFException();
    }

    @Override
    public long readLong() throws IOException {
        if(mBuffer.remaining()>7){
            return mBuffer.getLong();
        }
        throw new EOFException();
    }

    @Override
    public float readFloat() throws IOException {
        if(mBuffer.remaining()>3){
            return mBuffer.getFloat();
        }
        throw new EOFException();
    }

    @Override
    public double readDouble() throws IOException {
        if(mBuffer.remaining()>7){
            return mBuffer.getDouble();
        }
        throw new EOFException();
    }

    @Override
    public String readLine() {
        throw new UnsupportedOperationException();
    }

    @Override
    public String readUTF() {
        throw new UnsupportedOperationException();
    }

    @Override
    public int read() {
        if(mBuffer.remaining()>0){
            return mBuffer.get();
        }
        return -1;
    }

    public int read(byte[] dst,int off,int len){
        if (off<0 || off>=len){
            throw new IndexOutOfBoundsException();
        }
        int inlen=mBuffer.remaining();
        inlen=Math.min(inlen,len);
        mBuffer.get(dst,off,inlen);
        return inlen;
    }
}
